package com.tengju.bff.infrastructure.config;

import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.idanchuang.support.mybatis.crypt.CryptInterceptor;
import com.idanchuang.support.mybatis.crypt.config.CryptConfigBean;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.List;

@Configuration
@MapperScan(basePackages = {"com.tengju.data.infrastructure.persistence.mybatis.mapper.data.custom",
        "com.tengju.user.infrastructure.persistence.mybatis.mapper.data"},
        sqlSessionFactoryRef = "dataSqlSessionFactoryBean",
        sqlSessionTemplateRef = "dataSqlSessionTemplate"
)
public class DataDBConfig {

    @Value("${spring.datasource.data-url}")
    private String dataUrl;

    @Value("${spring.datasource.data-username}")
    private String dataDbUsername;

    @Value("${spring.datasource.data-password}")
    private String dataPassword;

    //  配置mapper的扫描，找到所有的mapper.xml映射文件
    @Value("classpath*:/mapper/**/*.xml")
    private String dataMapperLocations;

    @Bean
    public HikariDataSource dataDataSource() {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl(dataUrl);
        config.setUsername(dataDbUsername);
        config.setPassword(dataPassword);
        //是否自定义配置，为true时下面两个参数才生效
        config.addDataSourceProperty("cachePrepStmts", "true");
        //连接池大小默认25，官方推荐250-500
        config.addDataSourceProperty("prepStmtCacheSize", "250");
        //单条语句最大长度默认256，官方推荐2048
        config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
        //新版本MySQL支持服务器端准备，开启能够得到显著性能提升
        config.addDataSourceProperty("useServerPrepStmts", "true");
        config.addDataSourceProperty("useLocalSessionState", "true");
        config.addDataSourceProperty("useLocalTransactionState", "true");
        config.addDataSourceProperty("rewriteBatchedStatements", "true");
        config.addDataSourceProperty("cacheResultSetMetadata", "true");
        config.addDataSourceProperty("cacheServerConfiguration", "true");
        config.addDataSourceProperty("elideSetAutoCommits", "true");
        config.addDataSourceProperty("maintainTimeStats", "false");
        return new HikariDataSource(config);
    }

    @Bean
    public CryptInterceptor cryptInterceptor() {
        return new CryptInterceptor();
    }

    @Bean
    @ConfigurationProperties(prefix = "data-mysql.encryptor")
    public CryptConfigBean cryptConfigBean() {
        return new CryptConfigBean();
    }

    @Bean
    public SqlSessionFactory dataSqlSessionFactoryBean(List<Interceptor> interceptors,
                                                                  @Qualifier("dataDataSource") DataSource dataSource) throws Exception {
        MybatisSqlSessionFactoryBean dataSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
        dataSqlSessionFactoryBean.setDataSource(dataSource);
        Resource[] resources = new PathMatchingResourcePatternResolver()
                .getResources(dataMapperLocations);
        dataSqlSessionFactoryBean.setMapperLocations(resources);

        dataSqlSessionFactoryBean.setPlugins(interceptors.toArray(new Interceptor[]{}));
        return dataSqlSessionFactoryBean.getObject();
    }

    @Bean
    public SqlSessionTemplate dataSqlSessionTemplate(@Qualifier("dataSqlSessionFactoryBean") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean
    public DataSourceTransactionManager dataTransactionManager(@Qualifier("dataDataSource") DataSource dataSource) throws SQLException {
        return new DataSourceTransactionManager(dataSource);
    }
}
